package edu.towson.cosc.cosc455.jkingsbury.compiler;

import java.util.Stack;
import java.net.*;
import java.lang.Character;
import java.util.*;

import edu.towson.cosc.cosc455.interfaces.LexicalAnalyzer;

/**
 * @author jkings3
 *
 */

public class MyLexicalAnalyzer implements LexicalAnalyzer {

	private char nextCharacter;
	private char start = '#';
	private char lexeme[];
	private ArrayList words = new ArrayList();
	public Stack goodWord = new Stack();
    private int checked = 0;
	private String tag ;
	private String firstLine;
	private String text = "";
	private String twoWordStart = "#MAEK";
	private String secondTwoWord = "#GIMMEH";
	private String threeOne = "#I";
	private String threeTwo = "#I HAS";
	private String line = System.getProperty("line.seperator");
	 
	public void start(String line){
		firstLine = line;
		//Put string into character array to work with
		lexeme = firstLine.toCharArray();
		
	}
	
	@Override
	public void getNextToken() {
		getCharacter();
		//checked++;
		if(checked < lexeme.length){
			//If nextCharacter is a space, then loop until nextCharacter is not a space
			while(isSpace(nextCharacter)){
				getCharacter();
				//checked++;
			}
			//Checking tag
			if(nextCharacter == start){
				tag = processTag();   
				if(lookupToken(tag)){
					goodWord.push(tag);
					MyCompiler.token = tag;
					tag = "";
				}
				else{
					System.err.println("LEXICAL ERROR. Not a valid token. Token recieved: " + tag + " was not a legal token!");
					System.exit(0);
				}
				
			}//End of # character
			else if(isLegal(nextCharacter)){
				text = processText();
				goodWord.push(text);
				MyCompiler.token = text;
			}
			else{
				System.out.println("LEXICAL ERROR. Illegal character");
			}
		}
		//System.out.print("Stack: " );
		//printStack(goodWord);
	}


	private boolean isLegal(char nextCharacter2) {
		if(Character.isDefined(nextCharacter2)) return true;
		return false;
	}

	void printStack(Stack s) {
		//int count = 0;
		while(!s.empty()){
		      System.out.println(s.peek());
		      s.pop();
		   }
	}

	private String processTag() {
		String t = "";
		t = t + nextCharacter;
		getCharacter();
		
		while(!isSpace(nextCharacter) && nextCharacter != start && checked <= lexeme.length){
			t = t + nextCharacter;
			getCharacter();
		}
		if(t.equalsIgnoreCase(twoWordStart) || t.equalsIgnoreCase(secondTwoWord)){
			t = processTwoTag(t);
		}
		if(t.equalsIgnoreCase(threeOne)){
			t = processThreeTag(t);
		}
		return t;
	}

	private String processThreeTag(String text) {
		text += nextCharacter;//Append Space
		getCharacter();
		while(!isSpace(nextCharacter) && checked <= lexeme.length){
			text+= nextCharacter;
			getCharacter();
		}
		if(text.equalsIgnoreCase(threeTwo)){
			text += nextCharacter;//Append next space
			getCharacter();
			while(!isSpace(nextCharacter) && checked <= lexeme.length){
				text+= nextCharacter;
				getCharacter();
			}
		}
		return text;
	}

	private String processTwoTag(String text) {
		text += nextCharacter;//Append space
		getCharacter();
		while(!isSpace(nextCharacter) && checked <= lexeme.length){
			text+= nextCharacter;
			getCharacter();
		}
		return text;
	}

	private String processText() {
		String x = "";
		while(nextCharacter != start && checked <= lexeme.length){
			if(nextCharacter != start)
				x = x + nextCharacter;
			getCharacter();
			if(nextCharacter == start){
				checked--;
			}
		}
		return x;
	}

	@Override
	public void getCharacter() {
		//System.out.println(nextCharacter + " " + checked);
		if (checked < lexeme.length){
			nextCharacter = lexeme[checked];//Will read each character of the whole thing including spaces
		}
		checked++;
	}
	
	public char peek(){
		if (checked < lexeme.length){
			nextCharacter = lexeme[checked];//Will read each character of the whole thing including spaces
		}
		return nextCharacter;
	}
	
	@Override
	public boolean isSpace(char c) {//I changed this from a String to a char
		if (c == ' ' || c == '\n' || c == '\t' ){
			return true;
		}
		else return false;
	}

	public boolean isEnd(){
		//System.out.println("Length: " + lexeme.length);
		//System.out.println("Checked: " + checked);
		int length = lexeme.length;
		if (length < 18){
			return true;
		}
		int startEnd = length-8;
		String s = "";
		String z = "";
		for(int i = startEnd; i < length; i++){
			s += lexeme[i];
		}
		if (s.equalsIgnoreCase("#kthxbye")){
			//Check above it for double
			for(int i = lexeme.length-17; i < (startEnd-1); i++){
				z += lexeme[i];
			}
			//Here checks for a #kthxbye after the a #kthxbye
			if(z.equalsIgnoreCase("#kthxbye")) return false;//Something after end
			//Nothing after end
			return true;
		}
		//Something after end
		else return false;
	}
	@Override
	public boolean lookupToken(String token) {
		//This seems inefficient 
		//Check if the token is any legal tag, if it is return true
		//Else return false
		if (token.equalsIgnoreCase(LexicalTokens.DOC_START)) return true;//One
		if (token.equalsIgnoreCase(LexicalTokens.DOC_END)) return true;//One
		if (token.equalsIgnoreCase(LexicalTokens.BEGIN_HEAD)) return true;//Two
		if (token.equalsIgnoreCase(LexicalTokens.END_TAG)) return true;//One
		if (token.equalsIgnoreCase(LexicalTokens.COMM_BEGIN)) return true;//One
		if (token.equalsIgnoreCase(LexicalTokens.COMM_END)) return true;//One
		if (token.equalsIgnoreCase(LexicalTokens.TITLE_BEGIN)) return true;//Two
		if (token.equalsIgnoreCase(LexicalTokens.END_TAG_2)) return true;//One
		if (token.equalsIgnoreCase(LexicalTokens.BEGIN_PARA)) return true;//Two
		if (token.equalsIgnoreCase(LexicalTokens.BEGIN_BOLD)) return true;//Two
		if (token.equalsIgnoreCase(LexicalTokens.BEGIN_ITALIC)) return true;//Two
		if (token.equalsIgnoreCase(LexicalTokens.BEGIN_LIST)) return true;//Two
		if (token.equalsIgnoreCase(LexicalTokens.BEGIN_ITEM)) return true;//Two
		if (token.equalsIgnoreCase(LexicalTokens.BREAK)) return true;//Two
		if (token.equalsIgnoreCase(LexicalTokens.BEGIN_AUDIO)) return true;//Two
		if (token.equalsIgnoreCase(LexicalTokens.BEGIN_VIDEO)) return true;//Two
		if (token.equalsIgnoreCase(LexicalTokens.BEGIN_VAR)) return true;//Three
		if (token.equalsIgnoreCase(LexicalTokens.VARNAME)) return true;//One
		if (token.equalsIgnoreCase(LexicalTokens.VISIBLE)) return true;//One
		return false;
	}

}
